import os
import pickle
from twisted.web.client import getPage
from copy import deepcopy

class StatLister(object):
    honorprefix = "http://wol.swirve.com/kingdoms/Honor-"
    nwprefix = "http://wol.swirve.com/kingdoms/nw-"
    postfix = ".htm"
    
    listsize = 0
    nwlist = {}
    
    def __init__(self, messenger, channel):
        self.messenger = messenger
        self.channel = channel

    def nwList(self, kdlist):
        self.nwlist = {}
        self.nwtodo = kdlist
        self.getNextKD('NW')

    def getNextKD(self, option='NW'):
        if option == 'NW':
            if len(self.nwtodo):
                name, kd = self.nwtodo.popitem()
                loc = kd.location
                number = loc[0]
                island = loc[1]
                if number == 0:
                    self.getNextKD('NW')
                else:
                    d = getPage(self.nwprefix+str(island)+self.postfix)
                    d.addCallbacks(callback = lambda page:self.parseNW(page,number,island,name),
                                   errback = lambda error:println("Error: ", error))
            else:
                self.buildNWList()
                
    def parseNW(self, page, number, island, name):
        lines = page.splitlines()
        target = "("+str(number)+":"+str(island)
        for line in lines:
            if target in line:
                dummy = line.split('<TD ALIGN=RIGHT>')
                dummy = dummy[1]
                dummy = dummy.split('</TD>')
                NW = dummy[0]                
                self.nwlist[name] = NW
        self.getNextKD('NW')

    def buildNWList(self):
        kdlist = sorted(self.nwlist.items(), key=lambda(k,v):(v,k))
        kdlist.reverse()
        for kd in kdlist:
            self.messenger(self.channel, "%s : %s"%kd)


class Kingdom(object):
    name = ""
    location = (0,0)
    monarch = ""
    
    def __init__(self, name, location):
        self.name = name
        self.location = location
    
    def set_monarch(self, name):
        self.monarch = name
        return self.print_kd()
        
    def add_co(self, name):
        if not hasattr(self, 'comons'): self.comons = []
        if name in self.comons: return "%s is already a comonarch for %s."%(name, self.name)
        self.comons.append(name)
        return self.print_kd()
    
    def del_co(self, name):
        if not hasattr(self, 'comons'): self.comons = []
        if name not in self.comons: return "%s is not a comonarch for %s."%(name, self.name)
        self.comons.remove(name)
        return self.print_kd()
            
    def print_kd(self):
        if hasattr(self, 'comons'): cos = "".join(map(lambda co:"/%s"%co, self.comons))
        else: cos = ""
        return "%s (%d:%d) -%c5 %s%c10%s"%(self.name, self.location[0], self.location[1], 03, self.monarch, 03, cos)
    
    def set_loc(self, loc):
        self.location = loc
        return self.print_kd()


class KingdomListManager(object):
    triggers = ["!kds", "!kdlist", "!addkd", "!delkd", "!setmon", "!addco", "!delco", "!setloc", "!nwstats"]
    name = "kdlist"
    help = ["Kingdom listing commands:",
            "%c6!kdlist%c or %c6!kds%c"%(03,03,03,03),
            "%c6!addkd%c <kdname> <kdnumber> <islandnumber>"%(03,03),
            "%c6!setloc%c <kdname> <kdnumber> <islandnumber>"%(03,03),
            "%c6!delkd%c <kdname>"%(03,03),
            "%c6!setmon%c <kdname> <ircnick>"%(03,03),
            "%c6!addco%c <kdname> <ircnick>"%(03,03),
            "%c6!delco%c <kdname> <ircnick>"%(03,03)]

    kdlist = {}
    channel = "#tfprivate"
    
    def __init__(self, messenger):
        self.filename = "./kdlist.txt"
        self.statLister = StatLister(messenger, self.channel)
        if os.path.exists(self.filename):
            f = open(self.filename, 'r')
            self.kdlist = pickle.load(f)
            f.close()    

    def command(self, firstword, user, channel, msg):
        if channel != self.channel: return {'chanmsg':["Kingdom list functionality is only available in the monarchs' channel."]}
        if msg.lower() == "!kdlist" or msg.lower() == "!kds":
            return {'chanmsg': self.printkds()}
        if firstword == "!addkd":
            words = msg.split()
            if len(words) < 4: return {'chanmsg':["Usage: %c6!addkd%c <kdname> <kdnumber> <islandnumber>"%(03,03)]}
            island = words.pop()
            kdnumber = words.pop()            
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            try:
                island = int(island)
                kdnumber = int(kdnumber)
            except: return {'chanmsg':["Usage: %c6!addkd%c <kdname> <kdnumber> <islandnumber>"%(03,03)]}
            return {'chanmsg':[self.addkd(kdname, (kdnumber, island))]}
        if firstword == "!setloc":
            words = msg.split()
            if len(words) < 4: return {'chanmsg':["Usage: %c6!setloc%c <kdname> <kdnumber> <islandnumber>"%(03,03)]}
            island = words.pop()
            kdnumber = words.pop()            
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            try:
                island = int(island)
                kdnumber = int(kdnumber)
            except: return {'chanmsg':["Usage: %c6!setloc%c <kdname> <kdnumber> <islandnumber>"%(03,03)]}
            return {'chanmsg':[self.setloc(kdname, (kdnumber, island))]}
        if firstword == "!delkd":
            words = msg.split()
            if len(words) < 2: return {'chanmsg':["Usage: %c6!delkd%c <kdname>"%(03,03)]}
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            return {'chanmsg': [self.delkd(kdname)]}
        if firstword == "!setmon":
            words = msg.split()
            if len(words) < 3: return {'chanmsg':["Usage: %c6!setmon%c <kdname> <ircnick>"%(03,03)]}
            nick = words.pop()
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            return {'chanmsg': [self.setmon(kdname, nick)]}
        if firstword == "!addco":
            words = msg.split()
            if len(words) < 3: return {'chanmsg':["Usage: %c6!addco%c <kdname> <ircnick>"%(03,03)]}
            nick = words.pop()
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            return {'chanmsg': [self.addco(kdname, nick)]}
        if firstword == "!delco":
            words = msg.split()
            if len(words) < 3: return {'chanmsg':["Usage: %c6!delco%c <kdname> <ircnick>"%(03,03)]}
            nick = words.pop()
            kdname = "".join(map(lambda word:"%s "%word, words[1:])).rstrip()
            return {'chanmsg': [self.delco(kdname, nick)]}
        if msg == "!nwstats":
            self.statLister.nwList(deepcopy(self.kdlist))
            return {'chanmsg': ["Trying to compile NW list.."]}
        return {}

    def save(self):
        f = open(self.filename, 'w')
        pickle.dump(self.kdlist, f)
        f.close()
    
    def printkds(self):
        if len(self.kdlist) < 1: return ["No kingdoms listed."]
        names = self.kdlist.keys()
        names.sort(lambda x, y: cmp(x.lower(),y.lower()))
        return [self.kdlist[kd].print_kd() for kd in names]
    
    def addkd(self, kdname, loc):
        if self.kdlist.has_key(kdname): return "Kd already in the list."
        self.kdlist[kdname] = Kingdom(kdname, loc)
        self.save()
        return self.kdlist[kdname].print_kd()
    
    def delkd(self, kdname):
        if not self.kdlist.has_key(kdname): return "%s is not in the kd list."%kdname
        del self.kdlist[kdname]
        self.save()
        return "Removed %s from kd list."%kdname        
        
    def setmon(self, kdname, nick):
        if not self.kdlist.has_key(kdname): return "%s is not in the kd list."%kdname
        result = self.kdlist[kdname].set_monarch(nick)
        self.save()
        return result
    
    def addco(self, kdname, nick):
        if not self.kdlist.has_key(kdname): return "%s is not in the kd list."%kdname
        result = self.kdlist[kdname].add_co(nick)
        self.save()
        return result
    
    def delco(self, kdname, nick):
        if not self.kdlist.has_key(kdname): return "%s is not in the kd list."%kdname
        result = self.kdlist[kdname].del_co(nick)
        self.save()
        return result
    
    def setloc(self, kdname, loc):
        if not self.kdlist.has_key(kdname): return "%s is not in the kd list."%kdname
        result = self.kdlist[kdname].set_loc(loc)
        self.save()
        return result
        
